import 'dart:async';
import 'dart:io';

import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/cupertino.dart';
import 'package:get/get.dart';
import 'package:largefriends/config/lf_im_type.dart';
import 'package:largefriends/config/lf_route.dart';
import 'package:largefriends/entity/entities/chat_new_message_entity.dart';
import 'package:largefriends/entity/entities/lf_message_entity.dart';
import 'package:largefriends/entity/entities/pair.dart';
import 'package:largefriends/events/payment_success_event.dart';
import 'package:largefriends/net/error_handle.dart';
import 'package:largefriends/pages/lf_profile/lf_profile_logic.dart';
import 'package:largefriends/pages/lf_report/lf_report_logic.dart';
import 'package:largefriends/pages/lf_tab_message/lf_tab_message_logic.dart';
import 'package:largefriends/res/lf_string_ext.dart';
import 'package:largefriends/service/im/lf_im_contact_ext.dart';
import 'package:largefriends/service/im/lf_im_server_msg_ext.dart';
import 'package:largefriends/service/im/lf_im_service.dart';
import 'package:largefriends/service/im/lf_im_service_send_ext.dart';
import 'package:largefriends/service/lf_auth_service.dart';
import 'package:largefriends/utils/lf_dialog_utils.dart';
import 'package:wechat_camera_picker/wechat_camera_picker.dart';

import '../../entity/entities/lf_user_entity.dart';
import '../../events/delete_conversation_event.dart';
import '../../events/user_relation_event.dart';
import '../../service/manager/lf_event_helper.dart';
import '../../utils/lf_keyboard.dart';

toChatPage({required String uid, LfUserEntity? userEntity}) {
  Get.until(ModalRoute.withName(LFRoute.pathHome));
  Get.toNamed(LFRoute.pathChatDetail,
      arguments: {'uid': uid, 'userEntity': userEntity});
}

class LfChatDetailLogic extends GetxController {
  LfAuthService authService = Get.find();
  LfIMService imService = Get.find();
  LfTabMessageLogic messageLogic = Get.find();
  var _preEntity = ChatNewMessageEntity();
  final TextEditingController textEditingController = TextEditingController();

  Rx<ChatNewMessageEntity?> replyMessage = Rx<ChatNewMessageEntity?>(null);
  final FocusNode focusNode = FocusNode();
  LfUserEntity? other;
  late String otherUid;
  late LfUserEntity self;
  late MessageCallback callback;
  RxString content = "".obs;
  RxBool canChat = false.obs;
  RxBool isShowSticker = false.obs;
  RxBool isShowAudio = false.obs;
  AudioPlayer audioPlayer = AudioPlayer();
  RxString audioUrl = ''.obs;
  Rx<PlayerState> playerState = Rx<PlayerState>(PlayerState.completed);
  RxInt audioDuration = 0.obs;
  StreamSubscription? relationSubscription,
      deleteConversationSubscription,
      streamSubscriptionPaymentSuccess;
  @override
  void onInit() {
    self = authService.currentAccount!;
    otherUid = Get.arguments?['uid'] ?? "";
    other = Get.arguments?['userEntity'];
    super.onInit();
  }

  @override
  void onReady() {
    super.onReady();
    var messages = getMessages();
    if (messages.length < 50) {
      getHistory(lastId: "0");
    } else if (other != null &&
        messages.first.historyId != other!.lastMessageId) {
      ///消息列表和存储的最后一个lastId不一致了,也需要拉取
      getHistory(lastId: "0");
    }
    _initAudioPlayer();

    ///web socket 回调
    getChatUser();
    getCanChat();
    _initWsListener();
    cleanUpConversationListItemUnReadCount();
    relationSubscription =
        LfEventHelper().getEvent().on<UserRelationEvent>().listen((event) {
      if (event.uid != otherUid) {
        return;
      }
      if (event.type == UserRelationType.block) {
        Get.back();
      } else if (event.type == UserRelationType.like) {
        other?.liked = 1;
        if (other != null) {
          update();
        }
      } else if (event.type == UserRelationType.unlike) {
        other?.liked = 0;
        if (other != null) {
          update();
        }
      } else if (event.type == UserRelationType.wink) {
        other?.winked = 1;
        if (other != null) {
          update();
        }
      } else if (event.type == UserRelationType.requestPrivate) {
        other?.privateAlbumStatus = 2;
        if (other != null) {
          update();
        }
      } else if (event.type == UserRelationType.requestAccept) {
        other?.canAccessMyPrivate = 1;
        if (other != null) {
          update();
        }
      }
    });
    deleteConversationSubscription = LfEventHelper()
        .getEvent()
        .on<DeleteConversationEvent>()
        .listen((event) {
      if (event.uid == otherUid) {
        closeSoftKeyboard();
        Get.back();
      }
    });
    streamSubscriptionPaymentSuccess =
        LfEventHelper().getEvent().on<PaymentSuccessEvent>().listen((event) {
      ///如果升级成功了,需要把canchat map清空一下,防止无法聊天
      imService.canChatMap.clear();
      getCanChat();
    });
  }

  void getChatUser() async {
    await imService.getChatUser(otherUid).then((value) {
      other = value;
      update();
    }, onError: (error) {
      if (error is NetError) {
        ///TODO
      }
    });

    // if (result == null) {
    //   ///TODO
    //   // topTipMsg.value = 'net error!';
    //   //
    //   // ///网络请求失败
    //   // hideBottomInputAndFeedback.value = true;
    //   update();
    //   return;
    // } else {
    //   other = result;
    //
    //   ///TODO
    //   // if (other!.isBlockMe() || other!.isBlocked()) {
    //   //   hideBottomInputAndFeedback.value = true;
    //   // } else {}
    // }
    //
    // ///TODO
    //
    // // hasInit = true;
    // update();
  }

  void _initWsListener() {
    ///first judgment: connect status
    callback = (LfMessageEntity messageEntity) {
      ///只处理当前用户的信息 (可能要考虑chatRoom) TODO
      if (messageEntity.fromUid == otherUid ||
          messageEntity.toUid == otherUid) {
        var type = MessageTypeEnum.values.firstWhere(
            (element) => element.value == messageEntity.type,
            orElse: () => MessageTypeEnum.pong);
        switch (type) {
          case MessageTypeEnum.say:
            receiveAndUpdateConversationList(messageEntity);
            break;
          case MessageTypeEnum.recall:
            update();
            break;
          default:
            break;
        }
      }
    };

    ///second: add listener
    imService.addMessageCallBack(callback);
  }

  _initAudioPlayer() async {
    audioPlayer.onPlayerComplete.listen((event) {
      audioUrl.value = "";
      playerState.value = PlayerState.completed;
      audioDuration.value = 0;
    });

    audioPlayer.onPlayerStateChanged.listen((event) {
      if (event == PlayerState.stopped) {
        audioUrl.value = "";
        playerState.value = PlayerState.stopped;
        audioDuration.value = 0;
      } else if (event == PlayerState.paused) {
        playerState.value = PlayerState.paused;
      } else if (event == PlayerState.playing) {
        playerState.value = PlayerState.playing;
      }
    });
    audioPlayer.onPositionChanged.listen((event) {
      audioDuration.value = event.inMilliseconds;
    });
  }

  Future stopPlayAudio() async {
    await audioPlayer.stop();
    audioUrl.value = "";
    playerState.value = PlayerState.completed;
    audioDuration.value = 0;
  }

  getCanChat() async {
    var canChatResult = await imService.canChat(otherUid);
    if (canChatResult == 'true') {
      canChat.value = true;
    } else {
      canChat.value = false;
    }
  }

  @override
  void onClose() {
    imService.removeMessageCallBack(callback);
    stopPlayAudio();
    focusNode.unfocus();
    textEditingController.dispose();
    // IMService.instance.removeMessageCallBack(callback);
    // streamSubscriptionUserAction?.cancel();
    // streamSubscriptionUserAction = null;
    // streamSubscriptionUserInfo?.cancel();
    // streamSubscriptionUserInfo = null;
    audioPlayer.dispose();
    relationSubscription?.cancel();
    deleteConversationSubscription?.cancel();
    streamSubscriptionPaymentSuccess?.cancel();
    super.onClose();
  }

  void receiveAndUpdateConversationList(LfMessageEntity responseEntity) {
    //建立了联系，隐藏无联系时候展示的ui
    if (responseEntity.typeId == IMMessageType.text.value.toString() ||
        responseEntity.typeId == IMMessageType.image.value.toString() ||
        responseEntity.typeId == IMMessageType.voice.value.toString() ||
        responseEntity.typeId == IMMessageType.video.value.toString() ||
        responseEntity.typeId == IMMessageType.stickerAnim.value.toString() ||
        responseEntity.typeId == IMMessageType.stickerIcon.value.toString() ||
        responseEntity.typeId == IMMessageType.reply.value.toString() ||
        responseEntity.typeId == IMMessageType.customSticker.value.toString() ||
        responseEntity.typeId ==
            IMMessageType.messageTypeBolt.value.toString()) {
      //代表已经建立了联系
      other?.realChat = '1';
      if (isSender(responseEntity.fromUid)) {
        other?.sentMessageToUserStatus = "1";
      } else {
        other?.sentMessageStatus = 1;
      }
    }

    if (isSender(responseEntity.fromUid) == false) {
      imService.reportReadTime(responseEntity.fromUid);
    }
    if (responseEntity.typeId == IMMessageType.themeClear.value) {
      other?.backgroundUrl = '';
      other?.backgroundAttachId = '';
    }
    update();
  }

  getHistory({required String lastId}) async {
    imService.getMessageListFromNet(
        lastMessageId: lastId,
        uid: otherUid,
        success: () {
          updateChatItemShowTime();
        },
        error: (code, message) {
          showSnackBar(message);
        });
  }

  bool isSender(String? fromUid) {
    return self.userId == fromUid;
  }

  List<ChatNewMessageEntity> getMessages() {
    var list = imService.getMessageListFromMemory(otherUid);
    return list;
  }

  void updateChatItemShowTime() {
    processShowTime(getMessages());
    update();
  }

  void processShowTime(List<ChatNewMessageEntity> dataList) {
    for (int index = 0; index < dataList.length; index++) {
      if (dataList.length == 1) {
        //有且只有一条数据的时候
        dataList[0].shouldShowTime = true;
      } else {
        if (index == dataList.length - 1) {
          _preEntity = ChatNewMessageEntity();
          dataList[index].shouldShowTime = true;
        } else {
          _preEntity = dataList[index + 1];
          //根据之前的消息发送时间决定后一条消息时间需不需要显示
          if (_preEntity.created == 0) {
            dataList[index].shouldShowTime = true;
          } else {
            dataList[index].shouldShowTime =
                (dataList[index].created - _preEntity.created) * 1000 >
                    ((3 * 60000) + 1);
          }
        }
      }
    }
  }

  void sendTextMessage(String message) async {
    var text = message.trim().replaceBreak;
    if (text.isNullOrEmpty) {
      return;
    }
    if (replyMessage.value != null) {
      var replyInfo = ReplyInfo(
          historyId: replyMessage.value!.historyId,
          content: replyMessage.value?.message,
          toUsername: other?.username);
      await imService.sendReplyMessage(
          message: text!,
          receiverId: otherUid,
          replyInfo: replyInfo,
          insertLocal: () {
            updateChatItemShowTime();
          });

      replyMessage.value = null;
    } else {
      await imService.sendTextMessage(
          message: text!,
          receiverId: otherUid,
          insertLocal: () {
            updateChatItemShowTime();
          });
    }
    textEditingController.text = '';
    // EventManager().getEvent().fire(ScrollFirstEvent());
  }

  void sendStickerMessage({required String value}) async {
    await imService.sendSticker(
        message: value,
        receiverId: otherUid,
        imMessageType: IMMessageType.stickerAnim,
        insertLocal: () {
          updateChatItemShowTime();
        });
  }

  void cleanUpConversationListItemUnReadCount() {
    messageLogic.clearBadge(uid: otherUid);
  }

  void sendImageMessage(AssetEntity imageFile) async {
    Pair p = pairWidthAndHeight(
        imageFile.width.toDouble(), imageFile.height.toDouble());
    await imService.sendImage(
        receiverId: otherUid,
        entity: imageFile,
        width: p.left,
        height: p.right,
        insertLocal: () {
          updateChatItemShowTime();
        });
  }

  void sendAudioMessage(File file, {int duration = 1}) async {
    await imService.sendAudio(
        receiverId: otherUid,
        duration: duration,
        file: file,
        insertLocal: () {
          updateChatItemShowTime();
        });
    // EventManager().getEvent().fire(ScrollFirstEvent());
  }

  void recallMessage(ChatNewMessageEntity data) {
    if (data.messageType == IMMessageType.voice.value) {
      if (audioUrl.value == data.url && (data.url.isNullOrEmpty == false)) {
        stopPlayAudio();
      }
    }
    imService.sendRecall(
        receiverId: otherUid,
        entity: data,
        insertLocal: () {
          update();
        });
  }

  void reportMessage(ChatNewMessageEntity data) {
    closeSoftKeyboard();
    stopPlayAudio();
    toReportPage(userId: otherUid);
  }

  void jumpProfile() {
    stopPlayAudio();
    toProfilePage(uid: otherUid, userEntity: other);
  }
}

bool needShowTipMenu(
  ChatNewMessageEntity data,
  LfChatDetailLogic chatLogic,
) {
  if (chatLogic.other?.isSupport() == true) {
    return false;
  }
  bool isBlocked = chatLogic.other?.isBlockMe() ?? false;
  bool isEnable = chatLogic.other == null ? true : chatLogic.other!.status <= 1;
  if (isBlocked || !isEnable) {
    return false;
  }
  return (data.sendState == null ||
      data.sendState == 0 ||
      data.sendState == MessageStatusEnum.success.value ||
      data.sendState == MessageStatusEnum.read.value);
}
